package com.multysite.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import javax.cache.Cache;
import javax.cache.CacheException;
import javax.cache.CacheManager;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
import com.multysite.entity.Category;

public class CategoryModel {
	private static final Logger log = Logger.getLogger(CategoryModel.class
			.getName());

	private static Objectify ofy;

	private static Cache cache = null;

	private static boolean isRegisted = false;

	private static ObjectifyOpts opts = null;

	private static String cachePrefix = "categoryModel_";

	private List<Category> listResult = new ArrayList<Category>();

	private int limit = 30;

	private int page = 1;

	private int totalResult = 0;

	private int totalPage = 1;

	public int getTotalPage() {
		totalPage = totalResult / limit;
		if ((totalResult % limit) > 0) {
			totalPage += 1;
		}
		return totalPage;
	}

	public void setTotalPage(int totalPage) {
		this.totalPage = totalPage;
	}

	public int getLimit() {
		return limit;
	}

	public void setLimit(int limit) {
		this.limit = limit;
	}

	public int getPage() {
		return page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getTotalResult() {
		return totalResult;
	}

	public void setTotalResult(int totalResult) {
		this.totalResult = totalResult;
	}

	public List<Category> getListResult() {
		return listResult;
	}

	public void setListResult(List<Category> listResult) {
		this.listResult = listResult;
	}

	public static void init() {
		if (!isRegisted) {
			isRegisted = true;
			try {
				ObjectifyService.register(Category.class);
			} catch (Exception e) {
				isRegisted = false;
			}
			try {
				cache = CacheManager.getInstance().getCacheFactory()
						.createCache(Collections.emptyMap());
			} catch (CacheException e) {
				isRegisted = false;
			}
			opts = new ObjectifyOpts().setSessionCache(true);
		}
		ofy = ObjectifyService.begin(opts);
	}

	public CategoryModel() {
		init();
	}

	@SuppressWarnings("unchecked")
	public static void insert(Category obj) {
		init();
		if (cache != null) {
			cache.clear();
			String prefix = cachePrefix + "alias_" + obj.getAlias();
			cache.put(prefix, obj);
		}
		ofy.put(obj);
	}

	public static void delete(Category obj) {
		init();
		String prefix = cachePrefix + "alias_" + obj.getAlias();
		if (cache != null && cache.containsKey(prefix)) {
			cache.clear();
			cache.remove(prefix);
		}
		ofy.delete(obj);
	}

	@SuppressWarnings("unchecked")
	public static Category getById(String alias) {
		try {
			init();
			boolean cached = false;
			Category obj = new Category();
			String prefix = cachePrefix + "alias_" + alias;
			try {
				obj = (Category) cache.get(prefix);
				if (obj != null) {
					cached = true;
				}
			} catch (Exception e) {
				cached = false;
			}
			if (!cached) {
				try {
					obj = ofy.get(new Key<Category>(Category.class, alias));
					cache.put(prefix, obj);
				} catch (Exception e) {
					e.printStackTrace();
					obj = null;
				}
			}
			return obj;
		} catch (Exception e) {
			log.warning(e.toString());
			e.printStackTrace();
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public void prepareList() {
		try {
			listResult = new ArrayList<Category>();
			String prefix = cachePrefix + "list_" + page;
			String prefixTotal = cachePrefix + "list_total";
			String prefixLimit = cachePrefix + "list_limit";
			if (cache != null && cache.containsKey(prefix)
					&& cache.containsKey(prefixTotal)
					&& cache.containsKey(prefixLimit)) {
				listResult = (ArrayList<Category>) cache.get(prefix);
				totalResult = (Integer) cache.get(prefixTotal);
				limit = (Integer) cache.get(prefixLimit);
			} else {
				int start = (page - 1) * limit;
				Query<Category> q = ofy.query(Category.class);
				totalResult = q.count();
				q = q.limit(limit).offset(start);
				for (Category obj : q) {
					listResult.add(obj);
				}
				if (listResult.size() > 0) {
					cache.put(prefix, listResult);
					cache.put(prefixTotal, totalResult);
					cache.put(prefixLimit, limit);
				}
			}
		} catch (Exception e) {
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<Category>();
		}
	}

	@SuppressWarnings("unchecked")
	public void prepareAll() {
		try {
			listResult = new ArrayList<Category>();
			String prefix = cachePrefix + "all";
			if (cache != null && cache.containsKey(prefix)) {
				listResult = (ArrayList<Category>) cache.get(prefix);
			} else {
				Query<Category> q = ofy.query(Category.class);
				totalResult = q.count();
				for (Category obj : q) {
					listResult.add(obj);
				}
				if (listResult.size() > 0) {
					cache.put(prefix, listResult);
				}
			}
		} catch (Exception e) {
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<Category>();
		}
	}

	@SuppressWarnings("unchecked")
	public void prepareAllParrentList() {
		try {
			listResult = new ArrayList<Category>();
			String prefix = cachePrefix + "parentList";
			if (cache != null && cache.containsKey(prefix)) {
				listResult = (ArrayList<Category>) cache.get(prefix);
			} else {
				Query<Category> q = ofy.query(Category.class)
						.filter("level", 1);
				totalResult = q.count();
				for (Category obj : q) {
					listResult.add(obj);
				}
				if (listResult.size() > 0) {
					cache.put(prefix, listResult);
				}
			}
		} catch (Exception e) {
			log.warning(e.toString());
			e.printStackTrace();
			listResult = new ArrayList<Category>();
		}
	}
}
